import dmlib
import re
import os
import shutil
import subprocess
from dmlib import SyntaxError
from config import Config
from models import Zone, Record

def info(opt_dict, args):
    if args[1:2]:
        name = args[1]
    else:
        raise SyntaxError, (Config.MESSAGE["11"])
    
    model_zone = Zone()
    zone = model_zone.get_by_name(name)
    if zone:
        print """$TTL 3h
%s     IN      SOA     %s %s (
%s; serial number
%s; refresh time
%s; retry time
%s; expire time
%s; minimum ttl
)""" % (zone["name"], zone["source_host"], zone["contact_email"], zone["serial_number"], zone["refresh_time"], zone["retry_time"], zone["expire_time"], zone["minimum_ttl"])
    else:
        print Config.MESSAGE["13"]

def list(opt_dict, args):
    model_zone = Zone()
    model_record = Record()
    zone_list = model_zone.list()
    for zone in zone_list:
        if zone["enabled"]:
            status = "[ENABLED]"
        else:
            status = "[DISABLED]"
        print "====================="
        print status + " Created: " + zone['creation'].strftime("%A, %d. %B %Y %H:%M")
        print zone["name"].ljust(30) + " " + zone["source_host"].ljust(30) + " " + zone["contact_email"]
        record_list = model_record.list(zone["id"])
        for record in record_list:
            print "    " + record["name"].ljust(30) + " IN " + record["record_class"].ljust(4) + " " + record["value"].ljust(30) + " [RID=" + str(record["id"]) + "]"

def change_zone(opt_dict, args):
    model_zone = Zone()
    if args[1:2]:
        name = args[1]
        zone = model_zone.get_by_name(name)
        if not zone:
            raise SyntaxError, (Config.MESSAGE["13"])
    else:
        raise SyntaxError, (Config.MESSAGE["12"])
        
    # source host
    if "--source-host" in opt_dict:
        source_host = opt_dict["--source-host"]
    else:
        source_host = zone["source_host"]
    # lookup
    forward_lookup = zone["forward_lookup"]
    if "--reverse-lookup" in opt_dict: # reverse lookup
        forward_lookup = False
    if "--forward-lookup" in opt_dict: # forward lookup
        forward_lookup = True
    # enabled
    enabled = zone["enabled"]
    if "--enabled" in opt_dict:
        enabled = True
    if "--disabled" in opt_dict:
        enabled = False
    # contact email
    if "--contact-email" in opt_dict:
        contact_email = opt_dict["--contact-email"]
        contact_email = re.sub(r"[@]", ".", contact_email)
    else:
        contact_email = zone["contact_email"]
    # serial number
    if "--serial-number" in opt_dict:
        serial_number = opt_dict["--serial-number"]
    else:
        serial_number = zone["serial_number"]
    # refresh-time
    if "--refresh-time" in opt_dict:
        refresh_time = opt_dict["--refresh-time"]
    else:
        refresh_time = zone["refresh_time"]
    # retry time
    if "retry-time" in opt_dict:
        retry_time = opt_dict["--retry-time"]
    else:
        retry_time = zone["retry_time"]
    # expire time
    if "--expire-time" in opt_dict:
        expire_time = opt_dict["--expire-time"]
    else:
        expire_time = zone["expire_time"]
    # minimum ttl
    if "--minimum-ttl" in opt_dict:
        minimum_ttl = opt_dict["--minimum-ttl"]
    else:
        minimum_ttl = zone["minimum_ttl"]
        
    model_zone.update(zone["id"], forward_lookup, serial_number, refresh_time, retry_time, expire_time, minimum_ttl, source_host, contact_email, enabled)
    print Config.MESSAGE["9"]
    
def remove_zone(opt_dict, args):
    zone_model = Zone()
    if args[1:2]:
        name = args[1]
        zone = zone_model.get_by_name(name)
        if not zone:
            raise SyntaxError, (Config.MESSAGE["13"])
    else:
        raise SyntaxError, (Config.MESSAGE["14"])
    
    zone_model.remove(zone["id"])
    record_model = Record()
    record_model.remove_by_zone_id(zone["id"])
    print Config.MESSAGE["8"]
        
def add_zone(opt_dict, args):
    if args[1:2]:
        name = args[1]
    else:
        raise SyntaxError, (Config.MESSAGE["15"])
    # options
    # source host
    if "--source-host" in opt_dict:
        source_host = opt_dict["--source-host"]
    else:
        raise SyntaxError, (Config.MESSAGE["16"])
    # contact email
    if "--contact-email" in opt_dict:
        contact_email = opt_dict["--contact-email"]
        contact_email = re.sub(r"[@]", ".", contact_email)
    else:
        contact_email = Config.ZONE_CONTACT_EMAIL
    # lookup
    forward_lookup = Config.ZONE_FORWARD_LOOKUP
    if "--reverse-lookup" in opt_dict: # reverse lookup
        forward_lookup = False
    if "--forward-lookup" in opt_dict: # forward lookup
        forward_lookup = True
    # enabled
    enabled = Config.ZONE_ENABLED
    if "--enabled" in opt_dict:
        enabled = True
    if "--disabled" in opt_dict:
        enabled = False
    # serial number
    if "--serial-number" in opt_dict:
        serial_number = opt_dict["--serial-number"]
    else:
        serial_number = Config.ZONE_SERIAL_NUMBER
    # refresh-time
    if "--refresh-time" in opt_dict:
        refresh_time = opt_dict["--refresh-time"]
    else:
        refresh_time = Config.ZONE_REFRESH_TIME
    # retry time
    if "retry-time" in opt_dict:
        retry_time = opt_dict["--retry-time"]
    else:
        retry_time = Config.ZONE_RETRY_TIME
    # expire time
    if "--expire-time" in opt_dict:
        expire_time = opt_dict["--expire-time"]
    else:
        expire_time = Config.ZONE_EXPIRE_TIME
    # minimum ttl
    if "--minimum-ttl" in opt_dict:
        minimum_ttl = opt_dict["--minimum-ttl"]
    else:
        minimum_ttl = Config.ZONE_MINIMUM_TTL

    zone_model = Zone()
    zone_model.add(name, forward_lookup, serial_number, refresh_time, retry_time, expire_time, minimum_ttl, source_host, contact_email, enabled)
    print Config.MESSAGE["10"]

def add_record(opt_dict, args):
    # name
    if args[1:2]:
        name = args[1]
        name = name.lower()
        if not dmlib.is_domain(name):
            raise SyntaxError, (Config.MESSAGE["17"])
    else:
        raise SyntaxError, (Config.MESSAGE["18"])
    # options
    model_zone = Zone()
    # zone
    if "--zone" in opt_dict:
        zone_name = opt_dict["--zone"]
        print zone_name
        zone = model_zone.get_by_name(zone_name)
        if not zone:
            raise SyntaxError, (Config.MESSAGE["13"])
    else:
        raise SyntaxError, (Config.MESSAGE["19"])
    # record_class
    if "--record-class" in opt_dict:
        record_class = opt_dict["--record_class"]
        record_class = record_class.upper()
        if not record_class in ["NS", "A", "CNAME", "PTR"]:
            raise SyntaxError, (Config.MESSAGE["20"])
    else:
        record_class = Config.RECORD_CLASS
    # enabled
    enabled = Config.ZONE_ENABLED
    if "--enabled" in opt_dict:
        enabled = True
    if "--disabled" in opt_dict:
        enabled = False
    # value
    if "--value" in opt_dict:
        value = opt_dict["--value"]
        value = value.lower()
        if not ((record_class == "A" and dmlib.is_ip(value)) or (record_class in ["NS", "CNAME", "PTR"] and dmlib.is_domain(value))):
            raise SyntaxError, (Config.MESSAGE["21"])
    else:
        raise SyntaxError, (Config.MESSAGE["22"])
    
    model_record = Record()
    model_record.add(name, value, record_class, enabled, zone["id"])
    print Config.MESSAGE["7"]
    
def change_record(opt_dict, args):
    model_record = Record()
    # rid
    if args[1:2]:
        rid = args[1]
        record = model_record.get(rid)
        if not record:
            raise SyntaxError, (Config.MESSAGE["23"])
    else:
        raise SyntaxError, (Config.MESSAGE["24"])
    # options
    model_zone = Zone()
    # zone
    if "--zone" in opt_dict:
        zone_name = opt_dict["--zone"]
        zone = model_zone.get_by_name(zone_name)
        if not zone:
            raise SyntaxError, (Config.MESSAGE["13"])
    else:
        zone = model_zone.get(record["zone_id"])
    # record_class
    if "--record-class" in opt_dict:
        record_class = opt_dict["--record_class"]
        record_class = record_class.upper()
        if not record_class in ["NS", "A", "CNAME", "PTR"]:
            raise SyntaxError, (Config.MESSAGE["20"])
    else:
        record_class = record["record_class"]
    # name
    if "--name" in opt_dict:
        name = opt_dict["--name"]
        name = name.lower()
        if not dmlib.is_domain(name):
            raise SyntaxError, (Config.MESSAGE["17"])
    else:
        name = record["name"]
    # enabled
    enabled = record["enabled"]
    if "--enabled" in opt_dict:
        enabled = True
    if "--disabled" in opt_dict:
        enabled = False
    # value
    if "--value" in opt_dict:
        value = opt_dict["--value"]
        value = value.lower()
        if not ((record_class == "A" and dmlib.is_ip(value)) or (record_class in ["NS", "CNAME", "PTR"] and dmlib.is_domain(value))):
            raise SyntaxError, ("Value incorrect")
    else:
        value = record["value"]
    
    model_record = Record()
    model_record.change(record["id"], name, value, record_class, enabled, zone["id"])
    print Config.MESSAGE["6"]

def remove_record(opt_dict, args):
    model_record = Record()
    if "--rid" in opt_dict:
        rid = opt_dict["--rid"]
        record = model_record.get(rid)
        if not record:
            raise SyntaxError, (Config.MESSAGE["23"])
    else:
        raise SyntaxError, (Config.MESSAGE["24"])
    model_record.remove(record["id"])
    print Config.MESSAGE["5"]

def sync(opt_dict, args):
    shutil.rmtree(Config.NAMED_ZONE_DIR)
    os.mkdir(Config.NAMED_ZONE_DIR)
    conf_inc = open(Config.NAMED_CONF_INC, "w")
    model_zone = Zone()
    model_record = Record()
    zone_list = model_zone.list_enabled()
    for zone in zone_list:
        zone_info = """zone %s IN {
type master;
file "%s";
};
""" % (zone["name"], zone["name"])
        conf_inc.write(zone_info)
        zone_file = open(Config.NAMED_ZONE_DIR + "/" + zone["name"], "w")
        zone_soa = """$TTL 3h
%s     IN      SOA     %s %s (
%s; serial number
%s; refresh time
%s; retry time
%s; expire time
%s; minimum ttl
)""" % (zone["name"], zone["source_host"], zone["contact_email"], zone["serial_number"], zone["refresh_time"], zone["retry_time"], zone["expire_time"], zone["minimum_ttl"])
        zone_file.write(zone_soa)
        record_list = model_record.list_enabled(zone["id"])
        for record in record_list:
            record_info = "\n" + record["name"] + "\tIN\t" + record["record_class"] + "\t" + record["value"]
            zone_file.write(record_info)
        zone_file.close()
    conf_inc.close()
    subprocess.call(['/sbin/service', 'named', 'configtest'])
    subprocess.call(['/sbin/service', 'named', 'reload'])
    